package com.cy.stone.system.application.impl;

import cn.hutool.crypto.SecureUtil;
import com.cy.stone.common.constant.Constant;
import com.cy.stone.common.errorcode.AuthErrorCode;
import com.cy.stone.common.enums.UserStatus;
import com.cy.stone.common.properties.PasswordProperties;
import com.cy.stone.system.application.AuthApi;
import com.cy.stone.system.domain.clientobject.auth.LoginCO;
import com.cy.stone.system.infrastructure.database.entity.UserEntity;
import com.cy.stone.system.infrastructure.database.entity.UserPasswordEntity;
import com.cy.stone.system.infrastructure.database.service.IUserPasswordService;
import com.cy.stone.system.infrastructure.database.service.IUserService;
import com.feiniaojin.gracefulresponse.GracefulResponseException;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.Objects;
import java.util.Optional;

import static com.cy.stone.system.infrastructure.database.table.UserPasswordTableDef.USER_PASSWORD_ENTITY;
import static com.cy.stone.system.infrastructure.database.table.UserEntityTableDef.USER_ENTITY;

/**
 * 认证接口实现
 * @author Wings
 * @since 2023-12-15
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class AuthApiImpl implements AuthApi {

    private final IUserService userService;

    private final IUserPasswordService userPasswordService;

    private final PasswordProperties passwordProperties;

    @Override
    public void auth(LoginCO loginCO) {
        // 根据用户名查询用户信息
        UserEntity userEntity = userService.getOne(QueryWrapper.create()
                .from(USER_ENTITY).where(USER_ENTITY.USER_NAME.eq(loginCO.getUserName())));
        if (Objects.isNull(userEntity)) {
            // 用户不存在
            log.error(loginCO.getUserName() + "用户不存在");
            throw new GracefulResponseException(AuthErrorCode.USER_NOT_EXIST.getCode(), AuthErrorCode.USER_NOT_EXIST.getMessage());
        } else {
            if (!Objects.equals(userEntity.getStatus(), UserStatus.STATUS_ACTIVE.getCode())) {
                // 用户未启用
                log.error(loginCO.getUserName() + "用户状态未启用");
                throw new GracefulResponseException(AuthErrorCode.USER_INVALID.getCode(), AuthErrorCode.USER_INVALID.getMessage());
            } else {
                // 校验密码
                // 获取当前有效期内的密码
                Optional<UserPasswordEntity> optional = userPasswordService.getOneOpt(QueryWrapper.create().from(USER_PASSWORD_ENTITY)
                        .where(USER_PASSWORD_ENTITY.USER_NAME.eq(loginCO.getUserName()))
                        .and(USER_PASSWORD_ENTITY.START_DATE.le(LocalDate.now()))
                        .and(USER_PASSWORD_ENTITY.END_DATE.ge(LocalDate.now())));
                if (optional.isPresent()) {
                    // 校验密码是否一致
                    UserPasswordEntity userPasswordEntity = optional.get();
                    String inPassword = SecureUtil.md5(loginCO.getPassword() + userPasswordEntity.getSalt());
                    if (Objects.equals(inPassword, userPasswordEntity.getPassword())) {
                        // 校验密码错误次数是否已经达到
                        if (passwordProperties.getPwdErrorCount().compareTo(userPasswordEntity.getPwdErrorCount()) <= 0) {
                            // 禁用用户
                            userEntity.setStatus(UserStatus.STATUS_INACTIVE.getCode());
                            userEntity.setUpdateBy(loginCO.getUserName());
                            userService.updateById(userEntity);
                            log.error(loginCO.getUserName() + "密码错误次数超过上限");
                            throw new GracefulResponseException(AuthErrorCode.PASSWORD_ERROR_TOO_MUCH.getCode(), AuthErrorCode.PASSWORD_ERROR_TOO_MUCH.getMessage());
                        } else {
                            // 将密码错误次数重置为0次
                            userPasswordEntity.setPwdErrorCount(Constant.ZERO);
                            userPasswordEntity.setUpdateBy(loginCO.getUserName());
                            userPasswordService.updateById(userPasswordEntity);
                            log.info(loginCO.getUserName() + "登录认证通过");
                        }
                    } else {
                        log.error(loginCO.getUserName() + "密码错误");
                        throw new GracefulResponseException(AuthErrorCode.PASSWORD_ERROR.getCode(), AuthErrorCode.PASSWORD_ERROR.getMessage());
                    }
                } else {
                    log.error(loginCO.getUserName() + "无有效密码");
                    throw new GracefulResponseException(AuthErrorCode.PASSWORD_INVALID.getCode(), AuthErrorCode.PASSWORD_INVALID.getMessage());
                }
            }
        }
    }
}
